





<!DOCTYPE html>
<html class="writer-html5" lang="zh-CN" >
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>Relay 系统类型 &mdash; tvm 0.8.dev1982 文档</title>
  

  
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/gallery.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
  <link rel="stylesheet" href="../../_static/css/tlcpack_theme.css" type="text/css" />

  
  
    <link rel="shortcut icon" href="../../_static/tvm-logo-square.png"/>
  

  
  
  
  
    
      <script type="text/javascript" id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
        <script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
        <script src="../../_static/jquery.js"></script>
        <script src="../../_static/underscore.js"></script>
        <script src="../../_static/doctools.js"></script>
        <script src="../../_static/translations.js"></script>
    
    <script type="text/javascript" src="../../_static/js/theme.js"></script>

    
    <script type="text/javascript" src="../../_static/js/tlcpack_theme.js"></script>
    <link rel="index" title="索引" href="../../genindex.html" />
    <link rel="search" title="搜索" href="../../search.html" />
    <link rel="next" title="Algebraic Data Types in Relay" href="relay_adt.html" />
    <link rel="prev" title="Expressions in Relay" href="relay_expr.html" /> 
</head>

<body class="wy-body-for-nav">

   
  <div class="wy-grid-for-nav">
    
    
<header class="header">
    <div class="innercontainer">
      <div class="headerInner d-flex justify-content-between align-items-center">
          <div class="headerLogo">
               <a href="https://tvm.apache.org/"><img src=https://tvm.apache.org/assets/images/logo.svg alt="logo"></a>
          </div>

          <div id="headMenu" class="headerNav">
            <button type="button" id="closeHeadMenu" class="navCloseBtn"><img src="../../_static/img/close-icon.svg" alt="Close"></button>
             <ul class="nav">
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/community>Community</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/download>Download</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/vta>VTA</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/blog>Blog</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvm.apache.org/docs>Docs</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvmconf.org>Conference</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://github.com/apache/tvm/>Github</a>
                </li>
                <li class="nav-item">
                   <a class="nav-link" href=https://tvmchinese.github.io/declaration_zh_CN.html>About-Translators</a>
                </li>
             </ul>
               <div class="responsivetlcdropdown">
                 <button type="button" class="btn-link">
                   ASF
                 </button>
                 <ul>
                     <li>
                       <a href=https://apache.org/>Apache Homepage</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/licenses/>License</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/security/>Security</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/thanks.html>Thanks</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/events/current-event>Events</a>
                     </li>
                     <li>
                       <a href=https://www.zhihu.com/column/c_1429578595417563136>Zhihu</a>
                     </li>
                 </ul>
               </div>
          </div>
            <div class="responsiveMenuIcon">
              <button type="button" id="menuBtn" class="btn-menu"><img src="../../_static/img/menu-icon.svg" alt="Menu Icon"></button>
            </div>

            <div class="tlcDropdown">
              <div class="dropdown">
                <button type="button" class="btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                  ASF
                </button>
                <div class="dropdown-menu dropdown-menu-right">
                  <ul>
                     <li>
                       <a href=https://apache.org/>Apache Homepage</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/licenses/>License</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/security/>Security</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/foundation/thanks.html>Thanks</a>
                     </li>
                     <li>
                       <a href=https://www.apache.org/events/current-event>Events</a>
                     </li>
                     <li>
                       <a href=https://www.zhihu.com/column/c_1429578595417563136>Zhihu</a>
                     </li>
                  </ul>
                </div>
              </div>
          </div>
       </div>
    </div>
 </header>
 
    <nav data-toggle="wy-nav-shift" class="wy-nav-side fixed">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >
          

          
            <a href="../../index.html">
          

          
            
            <img src="../../_static/tvm-logo-small.png" class="logo" alt="Logo"/>
          
          </a>

          
            
            
                <div class="version">
                  0.8.dev1982
                </div>
            
          

          
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>

          
        </div>

        
        <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
          
            
            
              
            
            
              <p class="caption" role="heading"><span class="caption-text">如何开始</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../install/index.html">安装 TVM</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../contribute/index.html">贡献者指南</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">用户引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../tutorial/index.html">User Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../how_to/index.html">How To Guides</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">开发者引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../dev/tutorial/index.html">Developer Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev/how_to/how_to.html">开发者指南</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">架构指南</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../arch/index.html">Design and Architecture</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">主题引导</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../topic/microtvm/index.html">microTVM：裸机使用TVM</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../topic/vta/index.html">VTA: Versatile Tensor Accelerator</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">参考指南</span></p>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="index.html">语言参考</a><ul class="current">
<li class="toctree-l2 current"><a class="reference internal" href="index.html#introduction-to-relay">Relay简介</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="relay_expr.html">Expressions in Relay</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Relay 系统类型</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#type">类型</a></li>
<li class="toctree-l4"><a class="reference internal" href="#tensor-type">张量类型</a></li>
<li class="toctree-l4"><a class="reference internal" href="#tuple-type">元组类型</a></li>
<li class="toctree-l4"><a class="reference internal" href="#type-parameter">类型参数</a></li>
<li class="toctree-l4"><a class="reference internal" href="#type-constraint">类型约束</a></li>
<li class="toctree-l4"><a class="reference internal" href="#function-type">函数类型</a></li>
<li class="toctree-l4"><a class="reference internal" href="#type-relation">类型关系</a></li>
<li class="toctree-l4"><a class="reference internal" href="#incomplete-type">不完整类型</a></li>
<li class="toctree-l4"><a class="reference internal" href="#algebraic-data-types">代数数据类型</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="relay_adt.html">Algebraic Data Types in Relay</a></li>
<li class="toctree-l3"><a class="reference internal" href="relay_op.html">Relay 基础张量算子</a></li>
<li class="toctree-l3"><a class="reference internal" href="relay_pattern.html">Pattern Matching in Relay</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="index.html#hybrid-script">混合式脚本</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../api/python/index.html">Python API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api/links.html">Other APIs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../publications.html">Publications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../genindex.html">索引</a></li>
</ul>

            
          
        </div>
        
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
      
      <nav class="wy-nav-top" aria-label="top navigation" data-toggle="wy-nav-top">
        
            <div class="togglemenu">

            </div>
            <div class="nav-content">
              <!-- tvm -->
              Table of content
            </div>
        
      </nav>


      <div class="wy-nav-content">
        
        <div class="rst-content">
        

          




















<div role="navigation" aria-label="breadcrumbs navigation">

  <ul class="wy-breadcrumbs">
    
      <li><a href="../../index.html">Docs</a> <span class="br-arrow">></span></li>
        
          <li><a href="index.html">语言参考</a> <span class="br-arrow">></span></li>
        
      <li>Relay 系统类型</li>
    
    
      <li class="wy-breadcrumbs-aside">
        
            
            <a href="../../_sources/reference/langref/relay_type.rst.txt" rel="nofollow"> <img src="../../_static//img/source.svg" alt="viewsource"/></a>
          
        
      </li>
    
  </ul>

  
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
  <div class="section" id="relay-s-type-system">
<h1>Relay 系统类型<a class="headerlink" href="#relay-s-type-system" title="永久链接至标题">¶</a></h1>
<p>我们在详细介绍 Relay 的表达式语言的同时简要介绍了类型，但尚未描述其类型系统。 Relay 是一种静态类型和类型推断的语言，允许程序完全类型化的同时只需要少量显示的类型说明。</p>
<p>静态类型在执行编译器优化时很有用，因为它们无需运行程序即可传达有关程序操作的数据的属性，例如运行时形状、数据布局和存储。 Relay 的 <a class="reference internal" href="#algebraic-data-types">Algebraic Data Types</a> 允许轻松灵活地组合类型，以构建可以归纳推理并用于编写递归函数的数据结构。</p>
<p>Relay 的类型系统为形状提供了一种*依赖类型*的形式。也就是说，它的类型系统在 Relay 程序中跟踪张量的形状。将张量形状视为类型允许 Relay 在编译时执行更强大的推理；尤其值得一提，Relay 可以静态推理输出形状根据输入形状以复杂方式变化的操作。将形状推断作为类型推断问题允许 Relay 在编译时推断所有张量的形状，包括在使用分支和函数调用的程序中。</p>
<p>以这种方式对形状进行静态推理允许 Relay 提前编译，并提供有关张量的更多信息，以便在编译管道中进一步优化。这种优化可以通过传递来实现，即Relay到Relay的 AST 转换，并且可以使用推断的类型（例如，形状信息）来做出有关程序转换的决策。例如，<code class="code docutils literal notranslate"><span class="pre">src/relay/transforms/fuse_ops.cc</span></code> 给出了一个 pass 的实现，它使用推断的张量形状来用融合的运算符实现替换Relay程序中的运算符调用。</p>
<p>Relay 中关于张量类型的推理使用*类型关系* 进行编码，这意味着 Relay 中的大部分类型检查是约束解决（确保所有类型关系在调用点都得到满足）。类型关系提供了一种灵活且相对简单的方法，可以在 Relay 中使用依赖类型的强大功能，而不会大大增加其类型系统的复杂性。</p>
<p>下面我们详细介绍 Relay 中类型的语言以及它们如何分配给 Relay 表达式。</p>
<div class="section" id="type">
<h2>类型<a class="headerlink" href="#type" title="永久链接至标题">¶</a></h2>
<p>所有Relay类型的基本类型。所有 Relay 类型都是此基类型的子类。</p>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">Type</span></code>。</p>
</div>
<div class="section" id="tensor-type">
<h2>张量类型<a class="headerlink" href="#tensor-type" title="永久链接至标题">¶</a></h2>
<p>Relay 中的具体张量类型。</p>
<p>张量根据数据类型和形状进行类型化。目前，这些使用 TVM 的数据类型和形状，但在未来，Relay 可能包含一个单独的 AST 形状。特别是，数据类型包括:code:<cite>bool</cite>、<code class="code docutils literal notranslate"><span class="pre">float32</span></code>、<code class="code docutils literal notranslate"><span class="pre">int8</span></code> 和各种其他位宽和通道数。形状以维度元组形式给出（TVM <code class="code docutils literal notranslate"><span class="pre">IndexExpr</span></code>），例如:code:<cite>(5, 5)</cite>；标量也被赋予元组类型，并且具有 <code class="code docutils literal notranslate"><span class="pre">()</span></code> 的形状。</p>
<p>但是请注意，TVM 形状也可以包含变量和算术表达式，因此 Relay 的约束求解阶段将尝试找到所有形状变量的赋值，以确保所有形状在运行程序之前都是具体的。</p>
<p>例如，这是一个简单的具体张量类型，对应于 32 位浮点数的 10×10 张量：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Tensor</span><span class="p">[(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">float32</span><span class="p">]</span>
</pre></div>
</div>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">TensorType</span></code>。</p>
</div>
<div class="section" id="tuple-type">
<h2>元组类型<a class="headerlink" href="#tuple-type" title="永久链接至标题">¶</a></h2>
<p>Relay 中的一种元组。</p>
<p>正如元组只是一个静态已知长度的值序列，元组的类型由对应于元组每个成员的类型序列组成。</p>
<p>因为元组类型的大小是静态已知的，所以元组投影的类型只是元组类型的对应索引。</p>
<p>例如，在下面的代码中，<code class="code docutils literal notranslate"><span class="pre">%t</span></code> 的类型是 <code class="code docutils literal notranslate"><span class="pre">(Tensor[(),</span> <span class="pre">bool],</span> <span class="pre">Tensor[(10,</span> <span class="pre">10),</span> <span class="pre">float32])</span></code> 和 <code class="code docutils literal notranslate"><span class="pre">%c</span></code> 是类型：代码：<cite>Tensor[(10, 10), float32]</cite>。</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">let</span> <span class="o">%</span><span class="n">t</span> <span class="o">=</span> <span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="n">Constant</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">float32</span><span class="p">));</span>
<span class="n">let</span> <span class="o">%</span><span class="n">c</span> <span class="o">=</span> <span class="o">%</span><span class="n">t</span><span class="o">.</span><span class="mi">1</span><span class="p">;</span>
<span class="o">%</span><span class="n">c</span>
</pre></div>
</div>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">TupleType</span></code>。</p>
</div>
<div class="section" id="type-parameter">
<span id="id1"></span><h2>类型参数<a class="headerlink" href="#type-parameter" title="永久链接至标题">¶</a></h2>
<p>类型参数表示用于函数多态的占位符类型。类型参数根据 <em>kind</em> 指定，对应于这些参数允许替换的类型：</p>
<ul class="simple">
<li><p><code class="code docutils literal notranslate"><span class="pre">Type</span></code>，对应最高级 Relay 类型，如张量类型、元组类型和函数类型</p></li>
<li><p><code class="code docutils literal notranslate"><span class="pre">BaseType</span></code>，对应张量的基本类型（例如:code:<cite>float32</cite>、<code class="code docutils literal notranslate"><span class="pre">bool</span></code>）</p></li>
<li><p><code class="code docutils literal notranslate"><span class="pre">Shape</span></code>，对应一个张量形状</p></li>
<li><p><code class="code docutils literal notranslate"><span class="pre">ShapeVar</span></code>，对应张量形状内的变量</p></li>
</ul>
<p>Relay 的类型系统强制类型参数只允许出现在它们种类允许的地方，所以如果类型变量:code:<cite>t</cite> 是:code:<cite>Type</cite>，<code class="code docutils literal notranslate"><span class="pre">Tensor[t,</span> <span class="pre">float32]</span></code> 不是有效的类型。</p>
<p>与普通参数一样，必须在调用点为类型参数提供具体参数。</p>
<p>例如，下面的 <code class="code docutils literal notranslate"><span class="pre">s</span></code> 是一种类型为 <code class="code docutils literal notranslate"><span class="pre">Shape</span></code> 的类型参数，它将在下面的调用点替换为 <code class="code docutils literal notranslate"><span class="pre">(10,</span> <span class="pre">10)</span></code>：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>def @plus&lt;s : Shape&gt;(%t1 : Tensor[s, float32], %t2 : Tensor[s, float32]) {
     add(%t1, %t2)
}
plus&lt;(10, 10)&gt;(%a, %b)
</pre></div>
</div>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">TypeVar</span></code>。</p>
</div>
<div class="section" id="type-constraint">
<h2>类型约束<a class="headerlink" href="#type-constraint" title="永久链接至标题">¶</a></h2>
<p>这是一个表示类型约束的抽象类，将在后续版本中详细说明。目前，类型关系是唯一提供的类型约束；它们将在下面被讨论。</p>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">TypeConstraint</span></code>。</p>
</div>
<div class="section" id="function-type">
<h2>函数类型<a class="headerlink" href="#function-type" title="永久链接至标题">¶</a></h2>
<p>Relay 中的一个函数类型，更多细节参见 <cite>tvm/relay/type.h</cite></p>
<p>这是分配给 Relay 功能的类型。函数类型由类型参数列表、类型约束集、参数类型序列和返回类型组成。</p>
<p>我们非正式地将函数类型写为：<code class="code docutils literal notranslate"><span class="pre">fn&lt;type_params&gt;(arg_types)</span> <span class="pre">-&gt;</span> <span class="pre">ret_type</span> <span class="pre">where</span> <span class="pre">type_constraints</span></code></p>
<p>函数类型中的类型参数可能出现在参数类型或返回类型中。此外，每个类型约束都必须在函数的每个调用点保持。类型约束通常采用函数的参数类型和函数的返回类型作为参数，但也可能采用子集。</p>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">FuncType</span></code>。</p>
</div>
<div class="section" id="type-relation">
<span id="id2"></span><h2>类型关系<a class="headerlink" href="#type-relation" title="永久链接至标题">¶</a></h2>
<p>类型关系是 Relay 中最复杂的类型系统特性。它允许用户使用新规则扩展类型推断。我们使用类型关系为以复杂方式处理张量形状的运算符定义类型，例如广播运算符或 <code class="code docutils literal notranslate"><span class="pre">flatten</span></code>，允许 Relay 在这些情况下静态推理形状。</p>
<p>类型关系：code：<cite>R</cite> 描述了 Relay 函数的输入和输出类型之间的关系。也就是说，<code class="code docutils literal notranslate"><span class="pre">R</span></code> 是一个类型上的函数，如果关系成立，则输出 <cite>true</cite>，如果关系不成立，则输出 <cite>false</cite>。赋予关系的类型可能不完整或包含形状变量，因此类型推断必须为不完整的类型和形状变量来分配适当的值，以便保持必要的关系，如果存在此类值。</p>
<p>例如，我们可以定义一个身份关系为：</p>
<div class="highlight-prolog notranslate"><div class="highlight"><pre><span></span><span class="nv">Identity</span><span class="p">(</span><span class="nv">I</span><span class="p">,</span> <span class="nv">I</span><span class="p">)</span> <span class="p">:-</span> <span class="s s-Atom">true</span>
</pre></div>
</div>
<p>通过定义特定于该运算符的关系，在 Relay 中键入运算符通常很方便，该关系对参数类型和返回类型的所有必要约束进行编码。例如，我们可以定义 <code class="code docutils literal notranslate"><span class="pre">flatten</span></code> 的关系：</p>
<div class="highlight-prolog notranslate"><div class="highlight"><pre><span></span><span class="nv">Flatten</span><span class="p">(</span><span class="nv">Tensor</span><span class="p">(</span><span class="s s-Atom">sh</span><span class="p">,</span> <span class="s s-Atom">bt</span><span class="p">),</span> <span class="nv">O</span><span class="p">)</span> <span class="p">:-</span>
  <span class="nv">O</span> <span class="o">=</span> <span class="nv">Tensor</span><span class="p">(</span><span class="s s-Atom">sh</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nf">prod</span><span class="p">(</span><span class="s s-Atom">sh</span><span class="p">[</span><span class="mi">1</span><span class="s s-Atom">:</span><span class="p">]))</span>
</pre></div>
</div>
<p>如果我们有一个像 <code class="code docutils literal notranslate"><span class="pre">Broadcast</span></code> 这样的关系，就可以输入像 <code class="code docutils literal notranslate"><span class="pre">add</span></code> 这样的运算符：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">add</span> <span class="p">:</span> <span class="n">fn</span><span class="o">&lt;</span><span class="n">t1</span> <span class="p">:</span> <span class="n">Type</span><span class="p">,</span> <span class="n">t2</span> <span class="p">:</span> <span class="n">Type</span><span class="p">,</span> <span class="n">t3</span> <span class="p">:</span> <span class="n">Type</span><span class="o">&gt;</span><span class="p">(</span><span class="n">t1</span><span class="p">,</span> <span class="n">t2</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">t3</span>
            <span class="n">where</span> <span class="n">Broadcast</span>
</pre></div>
</div>
<p>上面包含 <code class="code docutils literal notranslate"><span class="pre">Broadcast</span></code> 表示参数类型和返回类型必须是张量，其中 <code class="code docutils literal notranslate"><span class="pre">t3</span></code> 的形状是 <code class="code docutils literal notranslate"><span class="pre">t1</span></code> 和 :code:` 的形状的广播t2`。类型系统将接受任何参数类型并返回类型，只要它们满足:code:<cite>Broadcast</cite>。</p>
<p>请注意，上面的示例关系是用类似 Prolog 的语法编写的，但目前这些关系必须由用户在 C++ 或 Python 中实现。更具体地说，Relay 的类型系统使用 <em>ad hoc</em> 求解器来处理类型关系，其中类型关系实际上是作为 C++ 或 Python 函数实现的，这些函数检查关系是否成立并强制更新任何形状变量或不完整类型。在当前的实现中，如果关系不成立，实现关系的函数应该返回:code:<cite>False</cite>，如果关系成立或者没有足够的信息来确定它是否成立，则返回:code:<cite>True</cite>。</p>
<p>所有关系的函数都会根据需要运行（如果输入被更新），直到满足以下条件之一：</p>
<ol class="arabic simple">
<li><p>所有关系都成立并且没有不完整的类型保留（类型检查成功）。</p></li>
<li><p>关系不成立（类型错误）。</p></li>
<li><p>在形状变量或不完整类型保留的位置达到固定点（可能需要类型错误或更多类型注释）。</p></li>
</ol>
<p>目前 Relay 中使用的所有关系都是用 C++ 实现的。有关在 C++ 中实现的关系示例，请参阅 <code class="code docutils literal notranslate"><span class="pre">src/relay/op</span></code> 中的文件。</p>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">TypeRelation</span></code>。</p>
</div>
<div class="section" id="incomplete-type">
<h2>不完整类型<a class="headerlink" href="#incomplete-type" title="永久链接至标题">¶</a></h2>
<p>不完整类型是未知的类型或类型的一部分。这仅在类型推断期间使用。任何省略的类型注释都会被不完整的类型替换，稍后将被另一种类型替换。</p>
<p>在编程语言文献中，不完整的类型被称为“类型变量”或“类型漏洞”。我们使用名称“不完整类型”是为了更清楚地将它们与类型参数区分开来：类型参数必须绑定到一个函数并在调用点被具体的类型参数（实例化）替换，而不完整类型可能出现在程序的任何地方并在类型推断期间填写。</p>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">IncompleteType</span></code>。</p>
</div>
<div class="section" id="algebraic-data-types">
<span id="adt-typing"></span><h2>代数数据类型<a class="headerlink" href="#algebraic-data-types" title="永久链接至标题">¶</a></h2>
<p><em>注意：文本格式当前不支持 ADT。</em></p>
<p>代数数据类型 (ADT) 在 :ref:<a href="#id1"><span class="problematic" id="id2">`</span></a>他们的概述 中有更详细的描述&lt;adt-overview&gt;；本节描述它们在类型系统中的实现。</p>
<p>ADT 由一组命名构造函数定义，每个构造函数都接受特定类型的参数。 ADT 的实例是一个容器，它存储用于生成它的构造函数参数的值以及构造函数的名称；可以通过基于其构造函数进行匹配来解构实例来检索这些值。因此，ADT 有时被称为“标签联合”：与 C 风格联合一样，给定 ADT 的实例的内容在某些情况下可能具有不同的类型，但构造函数用作指示如何解释内容的标记。</p>
<p>从类型系统的角度来看，最相关的是 ADT 可以接受类型参数（构造函数参数可以是类型参数，但具有不同类型参数的 ADT 实例必须被视为不同的类型）并且是递归的（ADT 的构造函数可以采用该 ADT 的实例，因此可以归纳地建立像树或列表这样的 ADT）。类型系统中 ADT 的表示必须能够适应这些事实，如以下部分将详细说明。</p>
<div class="section" id="global-type-variable">
<h3>全局类型变量<a class="headerlink" href="#global-type-variable" title="永久链接至标题">¶</a></h3>
<p>为了简洁地表示 ADT，并允许递归 ADT 定义，ADT 定义以全局类型变量的形式被赋予一个handle来唯一标识它。每个 ADT 定义都被赋予一个新的全局类型变量作为handle，因此可以使用指针相等性来区分不同的 ADT 名称。</p>
<p>就 Relay 的类型系统而言，ADT 是按名称区分的；这意味着如果两个 ADT 具有不同的handle，即使它们的所有构造函数在结构上都相同，它们也会被视为不同的类型。</p>
<p>因此，ADT 定义中的递归就像全局函数的递归一样：构造函数可以简单地在其定义中引用 ADT handle（全局类型变量）。</p>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">GlobalTypeVar</span></code>。</p>
</div>
<div class="section" id="definitions-type-data">
<h3>定义（类型数据）<a class="headerlink" href="#definitions-type-data" title="永久链接至标题">¶</a></h3>
<p>除了名称之外，ADT 还需要存储用于定义它的构造函数以及其中使用的任何类型参数。这些被存储在模块中，:ref:<a href="#id1"><span class="problematic" id="id2">`</span></a>类似于全局函数定义`&lt;module-description&gt;。</p>
<p>在使用 ADT 进行类型检查时，类型系统有时必须使用 ADT 名称索引模块以查找有关构造函数的信息。例如，如果在匹配表达式子句中对构造函数进行模式匹配，则类型检查器必须检查构造函数的签名以确保任何绑定变量都被分配了正确的类型。</p>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">TypeData</span></code>。</p>
</div>
<div class="section" id="type-call">
<h3>类型调用<a class="headerlink" href="#type-call" title="永久链接至标题">¶</a></h3>
<p>由于 ADT 定义可以采用类型参数，因此 Relay 的类型系统将 ADT 定义视为 <a href="#id1"><span class="problematic" id="id2">*</span></a>类型级函数*（因为该定义采用类型参数并返回具有这些类型参数的 ADT 实例的类型）。因此，使用类型调用对 ADT 的任何实例进行类型化，该调用显式列出了提供给 ADT 定义的类型参数。</p>
<p>列出 ADT 实例的类型参数很重要，因为两个 ADT 实例使用不同的构造函数构建，但相同的类型参数属于 <em>相同类型</em>，而具有不同类型参数的两个 ADT 实例不应被视为相同类型（例如，整数列表不应与浮点张量对列表具有相同的类型）。</p>
<p>类型调用中的“函数”是 ADT handle，并且 ADT 定义中的每个类型参数必须有一个参数。 （没有参数的 ADT 定义意味着任何实例都不会传递给类型调用的类型参数）。</p>
<p>有关其定义和文档，请参阅 <code class="xref py py-class docutils literal notranslate"><span class="pre">TypeCall</span></code>。</p>
</div>
<div class="section" id="example-list-adt">
<h3>示例：List ADT<a class="headerlink" href="#example-list-adt" title="永久链接至标题">¶</a></h3>
<p>本小节使用简单列表 ADT（作为默认 ADT 包含在 Relay 中）来说明前几节中描述的结构。其定义如下：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">data</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">a</span><span class="o">&gt;</span> <span class="p">{</span>
  <span class="n">Nil</span> <span class="p">:</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="n">List</span>
  <span class="n">Cons</span> <span class="p">:</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">List</span><span class="p">[</span><span class="n">a</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">List</span>
<span class="p">}</span>
</pre></div>
</div>
<p>因此，全球类型变量：代码：”列表”是 ADT 的句柄。模块中列表 ADT 的类型数据指出：代码：’列表’需要一个类型参数，并具有两个构造器：：代码：’Nil’（带有签名：’fn（）&lt;a&gt;- &gt;列表[a]）和：’代码：’Cons’（带有签名：’fn（a，&lt;a&gt;列表[a]）-&gt;列表[a]）。在：代码：’Cons’构造器中反复引用的”列表”是通过使用构建器定义中的全球类型变量：代码：’列表’来完成的。</p>
<p>使用类型呼叫，下面两个列表的示例及其类型：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">Cons</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">Nil</span><span class="p">()))</span> <span class="c1"># List[Tensor[(), int32]]</span>
<span class="n">Cons</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">Cons</span><span class="p">((</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">Nil</span><span class="p">()))</span> <span class="c1"># List[(Tensor[(), int32], Tensor[(), int32])]</span>
</pre></div>
</div>
<p>请注意：代码：<cite>Nil()</cite> 可以是任何列表的实例，因为它不接受任何使用类型参数的参数。 （尽管如此，对于任何 <code class="code docutils literal notranslate"><span class="pre">Nil()</span></code> 的*特定* 实例，必须指定类型参数。）</p>
<p>这是因为类型参数不匹配而被类型系统拒绝的两个列表：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># attempting to put an integer on a list of int * int tuples</span>
<span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">Cons</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">Nil</span><span class="p">()))</span>
<span class="c1"># attempting to put a list of ints on a list of lists of int * int tuples</span>
<span class="n">Cons</span><span class="p">(</span><span class="n">Cons</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">Cons</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">Nil</span><span class="p">())),</span> <span class="n">Cons</span><span class="p">(</span><span class="n">Cons</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">Cons</span><span class="p">((</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">Nil</span><span class="p">())),</span> <span class="n">Nil</span><span class="p">()))</span>
</pre></div>
</div>
</div>
</div>
</div>


           </div>
           
          </div>
          

<footer>

    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="relay_adt.html" class="btn btn-neutral float-right" title="Algebraic Data Types in Relay" accesskey="n" rel="next">下一个 <span class="fa fa-arrow-circle-right"></span></a>
      
      
        <a href="relay_expr.html" class="btn btn-neutral float-left" title="Expressions in Relay" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> 上一个</a>
      
    </div>

<div id="button" class="backtop"><img src="../../_static//img/right.svg" alt="backtop"/> </div>
<section class="footerSec">
    <div class="footerHeader">
      <ul class="d-flex align-md-items-center justify-content-between flex-column flex-md-row">
        <li class="copywrite d-flex align-items-center">
          <h5 id="copy-right-info">© 2020 Apache Software Foundation | All right reserved</h5>
        </li>
      </ul>

    </div>

    <ul>
      <li class="footernote">Copyright © 2020 The Apache Software Foundation. Apache TVM, Apache, the Apache feather, and the Apache TVM project logo are either trademarks or registered trademarks of the Apache Software Foundation.</li>
    </ul>

</section>
</footer>
        </div>
      </div>

    </section>

  </div>
  

    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

  </body>
  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>

  
  
    
    <!-- Theme Analytics -->
    <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-75982049-2', 'auto');
    ga('send', 'pageview');
    </script>

    
   

</body>
</html>